home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Overview / Sample / Sample.a < prev    next >
Encoding:
Text File  |  1994-11-18  |  38.4 KB  |  996 lines  |  [TEXT/MPS ]

  1. *
  2. *    Apple Macintosh Developer Technical Support
  3. *
  4. *    MultiFinder-Aware Simple Sample Application
  5. *
  6. *    Sample
  7. *
  8. *    Sample.a    -    Assembler Source
  9. *
  10. *    Copyright © 1989 Apple Computer, Inc.
  11. *    All rights reserved.
  12. *
  13. *    Versions:    
  14. *        1.00            08/88
  15. *        1.01            11/88
  16. *        1.02            04/89
  17. *        1.03            06/89
  18. *        1.04            06/92
  19. *
  20. *    Components:
  21. *        Sample.p        June 1, 1989
  22. *        Sample.c        June 1, 1989
  23. *        SampleInit.c        June 2, 1992
  24. *        Sample.a        June 1, 1989
  25. *        Sample.inc1.a        June 1, 1989
  26. *        SampleMisc.a        June 1, 1989
  27. *        Sample.r        June 1, 1989
  28. *        Sample.h        June 1, 1989
  29. *        PSample.make        June 1, 1989
  30. *        CSample.make        June 1, 1989
  31. *        ASample.make        June 1, 1989
  32. *        CSample.π        June 2, 1992
  33. *        CSample.π.rsrc        June 2, 1992
  34. *
  35. *    Sample is an example application that demonstrates how to
  36. *    initialize the commonly used toolbox managers, operate 
  37. *    successfully under MultiFinder, handle desk accessories, 
  38. *    and create, grow, and zoom windows.
  39. *
  40. *    It does not by any means demonstrate all the techniques 
  41. *    you need for a large application. In particular, Sample 
  42. *    does not cover exception handling, multiple windows/documents, 
  43. *    sophisticated memory management, printing, or undo. All of 
  44. *    these are vital parts of a normal full-sized application.
  45. *
  46. *    This application is an example of the form of a Macintosh 
  47. *    application; it is NOT a template. It is NOT intended to be 
  48. *    used as a foundation for the next world-class, best-selling, 
  49. *    600K application. A stick figure drawing of the human body may 
  50. *    be a good example of the form for a painting, but that does not 
  51. *    mean it should be used as the basis for the next Mona Lisa.
  52. *
  53. *    We recommend that you review this program or TESample before 
  54. *    beginning a new application.
  55.  
  56. * This example program is to be considered an introduction to coding in the
  57. * MPW Assembly language.  This sample program demonstrates the use of RECORD,
  58. * PROC, WITH, MACROs, IMPORT, and other coding practices used by MPW.  Although
  59. * this code will not be compatible with other assemblers, there is enough code
  60. * contained within the procedures that demonstrate 68000 programming on the Mac.
  61.  
  62. * The main purpose of this example is to have an easy to understand sample
  63. * assembly program that follows very closely the same sample program available
  64. * in Pascal and C.  Programmers not familiar with assembly code should refer to
  65. * these high level versions and follow the procedures while examining the assembly
  66. * code.  This is a great way to learn how to read assembly listings, and that is
  67. * the first step in using a debugger.
  68.  
  69. * Stack frame strategy:
  70. * -----------------------------------------------
  71. * Here is an example of a typical stack frame.  An example of the stack frame
  72. * RECORD is shown.  Using this strategy for procedures makes life much easier
  73. * while writing assembly code.  The procedure outlined in Pascal here is
  74. * followed by the same outline in assembly.
  75.  
  76. * PROCEDURE MyProcedure (Param1: type, Param2: type, ParamN: type) Result1: type;
  77.  
  78. * VAR    Local1: type;
  79. *    Local2: type;
  80. *    LocalN: type;
  81.  
  82.  
  83. * MyProcedure    PROC    EXPORT            ; any source file can use this routine
  84.  
  85. * define registors that need to be saved as EQUATES (typically A3-A7 and D4-D7)
  86.  
  87. * StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  88. * Result1    DS.{size}            ; function's result returned to caller
  89. * ParamBegin    EQU    *            ; start parameters after this point
  90. * Param1    DS.{size}            ; the first parameter on the stack
  91. * Param2    DS.{size}            ; rest of the parameters passed by caller
  92. * ParamN    DS.{size}            ; the last parameter passed by caller
  93. * ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  94. * RetAddr     DS.L    1            ; place holder for return address
  95. * A6Link    DS.L    1            ; place holder for A6 link
  96. * Local1    DS.{size}            ; a local variable for this procedure only
  97. * Local2    DS.{size}            ; other local variables for this procedure
  98. * LocalN    DS.{size}            ; the last local variable
  99. * LocalSize    EQU     *            ; size of all the local variables
  100. *         ENDR
  101.  
  102. *         WITH    StackFrame        ; cover our local stack frame
  103. *         LINK    A6,#LocalSize        ; allocate our local stack frame
  104.  
  105. *        save registors trashed by this routine
  106.  
  107. *         # # INSERT YOUR CODE HERE # #
  108.  
  109. * Exit        restore registors trashed by this routine
  110. *         UNLK    A6            ; destroy the link
  111. *         MOVEA.L    (SP)+,A0        ; pull off the return address
  112. *         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  113. *         JMP    (A0)            ; return to the caller
  114. *         DbgInfo    MyProcedure        ; this name will appear in the debugger
  115. *         ENDP
  116.  
  117. * The Macro DbgInfo is optional.  I prefer to use it, since it aids in
  118. * debugging.  There are more macros in the "AStructMacs" folder of MPW.  Put on
  119. * a pot of coffee and take a look at them and the Sample program that uses these
  120. * macros.  There is one macro in particular that builds the entire stack frame
  121. * structure as outlined above, including the debug info.
  122.  
  123. * Segmentation strategy:
  124. * -----------------------------------------------
  125. * This program consists of three segments. Main contains most of the code.
  126. * Initialize contains code that is only used once, during startup, and can be
  127. * unloaded after the program starts. %A5Init is automatically created by the
  128. * Linker to initialize globals and constants, and is unloaded right away.
  129.  
  130. * SetPort strategy:
  131. * -----------------------------------------------
  132. * Tool box routines do not change the current port. In spite of this, in this
  133. * program we use a strategy of calling SetPort whenever we want to draw or
  134. * make calls which depend on the current port. This makes us less vulnerable
  135. * to bugs in other software which might alter the current port (such as the
  136. * bug (feature?) in many desk accessories which change the port on OpenDeskAcc).
  137. * Hopefully, this also makes the routines from this program more self-contained,
  138. * since they don't depend on the current port setting.
  139.  
  140. * ================================================
  141. * -------------- INCLUDES SECTION ----------------
  142. * ================================================
  143.     
  144.     PRINT    PUSH,OFF            ; don't print any of this stuff
  145.  
  146.     INCLUDE    'ToolEqu.a'
  147.     INCLUDE    'Traps.a'
  148.     INCLUDE    'PackMacs.a'
  149.     INCLUDE    'QuickEqu.a'
  150.     INCLUDE    'SysEqu.a'
  151.     INCLUDE    'Sample.inc1.a'            ; all our macros and data templates
  152.  
  153.     PRINT    POP                ; restore the PRINT options
  154.     
  155.  
  156. * ================================================
  157. * ---------  DATA STORAGE ALLOCATION  ------------
  158. * ================================================
  159. * Global data storage.  All global memory is allocated here.  The
  160. * Linker will load all global data offset from A5, and the Asm knows this.
  161. * Therefore, no reference to (A5) is required in the code. Hooray!
  162. * Here we declare two data structures using our templates defined previously.
  163. * They must be EXPORTed here for other files that need to IMPORT them.
  164.  
  165.         EXPORT    (QD,G):DATA
  166.  
  167. QD        DS    QDGlobals        ; QuickDraw's globals
  168. G        DS    AppGlobals        ; application's globals
  169.  
  170.  
  171. * ================================================
  172. * PROCEDURE Initialize;
  173. * ================================================
  174. * Set up the whole world, including global variables, Toolbox managers, and menus.
  175. * Check to see if a given trap is implemented. The recommended approach to see if
  176. * a trap is implemented is to see if the address of the trap routine is the same
  177. * as the address of the Unimplemented trap.  We also create our one application
  178. * window at this time.  Since window storage is non-relocateable, how and when to
  179. * allocate space for windows is very important so that heap fragmentation does not
  180. * occur.  Because Sample has only one window and it is only disposed when the
  181. * application quits, we will allocate its space here, before anything that might
  182. * be a locked relocatable object gets into the heap. This way, we can force its
  183. * storage to be in the lowest memory available in the heap. Window storage can
  184. * differ widely amongst applications depending on how many windows are created
  185. * and disposed.  If a failure occurs here, we will consider that the application
  186. * is in such bad shape that we should just exit. Your error handling may differ,
  187. * but the checks should still be made.
  188.  
  189. * If an error is detected, instead of merely doing an ExitToShell, which leaves
  190. * the user without much to go on, we call AlertUser, which puts up a simple alert
  191. * that just says an error occurred and then calls ExitToShell.  In the interests
  192. * of keeping things simple, the alert does not state the specific cause of the error,
  193. * but a more informative alert would be appropriate for more sophisticated applications.
  194. * Since there is no other cleanup needed at this point if an error is detected, this
  195. * form of error- handling is acceptable. If more sophisticated error recovery is needed,
  196. * a signal mechanism, such as is provided by Signals, can be used.
  197.  
  198. * Something worth noting here.  Since the AlertUser routine is in a different segment,
  199. * we have to use a Jump instruction to get there.  In other words, we must go through the
  200. * jump table.  This causes extra test and branch instructions to get over the JMP AlertUser.
  201.  
  202.         SEG 'Initialize'        ; case sensitive
  203. Initialize    PROC                ; Initialize everything
  204.  
  205. CountReg    EQU    D4            ; temporary registor to count loops
  206.  
  207. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  208. ParamBegin    EQU    *            ; start parameters after this point
  209. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  210. RetAddr     DS.L    1            ; place holder for return address
  211. A6Link        DS.L    1            ; place holder for A6 link
  212. CurMBar        DS.L    1            ; local handle to our menubar
  213. TheEvent     DS    EventRecord         ; local copy of the event record
  214. LocalSize    EQU     *            ; size of all the local variables
  215.         ENDR
  216.         
  217.         IMPORT    GoGetRect,AlertUser,SysEnvirons,    \
  218.             TrapAvailable        ; linked in with Interface.o
  219.  
  220.         WITH    StackFrame        ; cover our local stack frame
  221.         LINK    A6,#LocalSize        ; allocate our local stack frame
  222.         
  223.         MOVEM.L    CountReg,-(SP)         ; save the current registor values
  224.         MOVE.W    #False,G.InBackground    ; we start out in the foreground
  225.         MOVE.W    #True,G.Stopped        ; we'll start with the red light on
  226.  
  227. * ------------- INITIALIZE MANAGERS -------------
  228.  
  229. @1        PEA     QD.thePort         ; initialize all of the Managers
  230.         _InitGraf            ; please don't flush my events
  231.         _InitFonts
  232.         _InitWindows
  233.         _InitMenus
  234.         _TEInit
  235.         CLR.L    -(SP)    
  236.         _InitDialogs
  237.         _InitCursor
  238.         
  239. * Call MPPOpen and ATPLoad at this point to initialize AppleTalk, if you are using it.
  240. * NOTE -- It is no longer necessary, and actually unhealthy, to check PortBUse and
  241. * SPConfig before opening AppleTalk. The drivers are capable of checking for port
  242. * availability themselves.  This next bit of code is necessary to allow the default
  243. * button of our alert be outlined.
  244.      
  245. * ------------- WASTE THREE EVENTS -------------
  246.  
  247.         MOVE.W    #2,CountReg        ; set register value to loop 3 times
  248. Loop        CLR.W    -(SP)            ; space for result
  249.         MOVE.W    #EveryEvent,-(SP)    ; the events we want
  250.         PEA    TheEvent(A6)        ; pass a pointer to our event
  251.         _EventAvail
  252.         MOVE.W    (SP)+,D0        ; result code
  253.         DBF    CountReg,Loop        ; decrement count, if count < 0 then continue
  254.  
  255. * ------------- GET THE ENVIRONMENT -------------
  256.  
  257.         CLR.W    -(SP)            ; create space for result
  258.         MOVE.W    #EnvironsVersion,-(SP)    ; version of SysEnvirons we want
  259.         PEA    G.Mac            ; the global environment record
  260.         JSR    SysEnvirons        ; we can ignore any errors here,
  261.         MOVE.W    (SP)+,D0        ; SysEnvirons will fill in regardless
  262.         MOVE.W    G.Mac.MachineType,D0     ; negitive value means old ROMs
  263.         BPL.S    @2            ; 128k ROMs or better, continue on
  264.         JMP    AlertUser        ; we don't want to run on 64k ROMs
  265.  
  266. * ------------- TEST FOR WAITNEXTEVENT -------------
  267. * 1.02 - Move TrapAvailable call to after SysEnvirons so that
  268. * we can tell in TrapAvailable if a tool trap value is out of range.
  269.  
  270. @2        CLR.W    -(SP)            ; space for result of trap test
  271.         MOVE.W    #WaitNextEvent,-(SP)    ; pass the trap number of WaitNextEvent trap
  272.         BSR    TrapAvailable        ; test for this trap
  273.         MOVE.W    (SP)+,G.HasWNEvent    ; put the result in our global flag
  274.             
  275. * ------------- CHECK FOR ENOUGH MEMORY -------------
  276. * It is better to first check the size of the application heap against a value
  277. * that you have determined is the smallest heap the application can reasonably
  278. * work in. This number should be derived by examining the size of the heap that
  279. * is actually provided by MultiFinder when the minimum size requested is used.
  280. * The derivation of the minimum size requested from MultiFinder is described
  281. * in ASample.r. The check should be made because the preferred size can end up
  282. * being set smaller than the minimum size by the user. This extra check acts to
  283. * insure that your application is starting from a solid memory foundation.
  284.  
  285. *    IF applLimit - applZone < MinHeap THEN AlertUser
  286.  
  287. * Next, make sure that enough memory is free for your application to run. It
  288. * is possible for a situation to arise where the heap may have been of required
  289. * size, but a large scrap was loaded which left too little memory. To check for
  290. * this, call PurgeSpace and compare the result with a value that you have determined
  291. * is the minimum amount of free memory your application needs at initialization.
  292. * This number can be derived several different ways. One way that is fairly
  293. * straightforward is to run the application in the minimum size configuration
  294. * as described previously. Call PurgeSpace at initialization and examine the value
  295. * returned. However, you should make sure that this result is not being modified
  296. * by the scrap's presence. You can do that by calling ZeroScrap before calling
  297. * PurgeSpace. Make sure to remove that call before shipping, though.
  298.  
  299. * The extra benefit to waiting until after the Toolbox Managers have been initialized
  300. * before checking memory is that we can now give the user an alert to tell him what
  301. * happened. Although it is possible that the memory situation could be worsened by
  302. * displaying an alert, MultiFinder would gracefully exit the application with
  303. * an informative alert if memory became critical. Here we are acting more
  304. * in a preventative manner to avoid future disaster from low-memory problems.
  305.  
  306.         MOVE.L    applLimit,D1        ; get pointer to ApplLimit
  307.         MOVE.L    applZone,D0        ; get pointer to ApplicZone
  308.         SUB.L    D0,D1            ; subtract the ApplicZone from ApplLimit
  309.         CMPI.L    #MinHeap,D1        ; do we have enough memory?
  310.         BPL.S    @3            ; yes we do, continue on
  311.         JMP    AlertUser        ; no, report the error
  312.         
  313. @3        _PurgeSpace            ; results will be in A0 and D0
  314.         CMPI.L    #MinSpace,D0        ; do we have enough purgeable space?
  315.         BPL.S    @4
  316.         JMP    AlertUser        ; no, report the error
  317.  
  318. * ------------- SET UP THE TRAFFIC LIGHT WINDOW -------------
  319. * We will allocate our own window storage instead of letting the Window Manager
  320. * for two reasons. One, GetNewWindow locks the 'WIND' resource handle before calling
  321. * NewWindow and this can lead to heap fragmentation.  Two, it takes just as much time
  322. * for NewWindow to get the memory as it does for us to get it.
  323.  
  324. @4        MOVE.L    #windowSize,D0
  325.         _NewPtr ,Clear            ; create a pointer in A0 and clear memory
  326.         CMPA.L    #NIL,A0            ; check for NIL pointer (result in D0)
  327.         BNE.S    @5            ; must have been a valid pointer
  328.         JMP    AlertUser        ; couldn't get memory, report error
  329.         
  330. @5        CLR.L    -(SP)            ; create space for result
  331.         MOVE.W    #rWindow,-(SP)        ; out window resource definition
  332.         MOVE.L    A0,-(SP)        ; our window record storage
  333.         MOVE.L    #-1,-(SP)        ; make it on top
  334.         _GetNewWindow            ; create the window
  335.         MOVE.L    (SP)+,D0        ; we're not saving our window pointer
  336.         
  337. * ------------- SET UP THE MENUS -------------
  338.     
  339.         CLR.L    -(SP)            ; space for MenuBar handle
  340.         MOVE.W    #rMenuBar,-(SP)        ; our MenuBar resource
  341.         _GetNewMBar            ; the modern way, get a MenuBar
  342.         MOVE.L    (SP),CurMBar(A6)
  343.         _SetMenuBar
  344.         MOVEA.L    CurMBar(A6),A0        ; we're done with that handle
  345.         _DisposHandle            ; there is a result in D0
  346.         CLR.L    -(SP)
  347.         MOVE.W    #AppleMenu,-(SP)
  348.         _GetMHandle            ; put Apple menu handle on stack
  349.         MOVE.L    #'DRVR',-(SP)        ; get all the DAs
  350.         _AddResMenu
  351.         _DrawMenuBar
  352.  
  353. * ------------- SET UP RECTS FOR THE LIGHTS  -------------
  354.  
  355.         CLR.W    -(SP)            ; space for result of GoGetRect
  356.         MOVE.W    #rStopRect,-(SP)    ; pass the stop light's rect
  357.         PEA    G.StopRect        ; pass the stop light's rect pointer
  358.         BSR    GoGetRect        ; go get the stop light rect
  359.         MOVE.W    (SP)+,D0        ; get the result of GoGetRect
  360.         CMPI.W    #True,D0        ; did we get the RECT resource?
  361.         BEQ.S    @6            ; yes, then continue
  362.         JMP    AlertUser        ; otherwise, we're having some trouble
  363.         
  364. @6        CLR.W    -(SP)            ; space for result of GoGetRect
  365.         MOVE.W    #rGoRect,-(SP)        ; pass the go light's rect
  366.         PEA    G.GoRect        ; pass the go light's rect pointer
  367.         BSR    GoGetRect        ; go get the go light rect
  368.         MOVE.W    (SP)+,D0        ; get the result of GoGetRect
  369.         CMPI.W    #True,D0        ; did we get the RECT resource?
  370.         BEQ.S    Exit            ; yes, then continue
  371.         JMP    AlertUser        ; otherwise, we're having some trouble
  372.                 
  373. Exit        MOVEM.L    (SP)+,CountReg        ; restore the registors
  374.         UNLK    A6            ; destroy the link
  375.         MOVEA.L    (SP)+,A0        ; pull off the return address
  376.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  377.         JMP    (A0)            ; return to the caller
  378.  
  379.         DbgInfo    Initialz        ; this name will appear in the debugger
  380.         ENDP
  381.  
  382. * ================================================
  383. * PROCEDURE DoContentClick(window: WindowPtr; event: EventRecord);
  384. * ================================================
  385. * This is called when a mouse-down event occurs in the content of a window.
  386. * Other applications might want to call FindControl, TEClick, etc., to
  387. * further process the click.
  388.  
  389.         SEG    'Main'            ; case sensitive
  390. DoContentClick    PROC
  391.  
  392. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  393. ParamBegin    EQU    *            ; start parameters after this point
  394. WindowPtr    DS.L    1            ; passed parameter of the window pointer
  395. EventPtr    DS.L    1            ; pointer to the event record
  396. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  397. RetAddr     DS.L    1            ; place holder for return address
  398. A6Link        DS.L    1            ; place holder for A6 link
  399. LocalSize    EQU     *            ; size of all the local variables
  400.         ENDR
  401.         
  402.         IMPORT    SetLight
  403.  
  404.         WITH    StackFrame        ; cover our local stack frame
  405.         LINK    A6,#LocalSize        ; allocate our local stack frame
  406.  
  407.          MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  408.         MOVE.W    G.Stopped,D0        ; get current state of the light
  409.         EORI.W    #True,D0        ; exclusive OR the current state
  410.         MOVE.W    D0,-(SP)        ; pass new state to switch light
  411.         BSR    SetLight        ; set the traffic light
  412.  
  413. Exit        UNLK    A6            ; destroy the link
  414.         MOVEA.L    (SP)+,A0        ; pull off the return address
  415.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  416.         JMP    (A0)            ; return to the caller
  417.  
  418.         DbgInfo    DoContnt        ; this name will appear in the debugger
  419.         ENDP
  420.  
  421. * ================================================
  422. * PROCEDURE DoUpdate(window: WindowPtr);
  423. * ================================================
  424. * This is called when an update event is received for a window.
  425. * It calls DrawWindow to draw the contents of an application window.
  426. * As an efficiency measure that does not have to be followed, it
  427. * calls the drawing routine only if the visRgn is non-empty. This
  428. * will handle situations where calculations for drawing or drawing
  429. * itself is very time-consuming.
  430.  
  431.         SEG    'Main'            ; case sensitive
  432. DoUpdate    PROC
  433.  
  434. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  435. ParamBegin    EQU    *            ; start parameters after this point
  436. WindowPtr    DS.L    1            ; passed parameter of the window pointer
  437. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  438. RetAddr     DS.L    1            ; place holder for return address
  439. A6Link        DS.L    1            ; place holder for A6 link
  440. LocalSize    EQU     *            ; size of all the local variables
  441.         ENDR
  442.         
  443.         IMPORT    IsAppWindow,DrawWindow
  444.  
  445.         WITH    StackFrame        ; cover our local stack frame
  446.         LINK    A6,#LocalSize        ; allocate our local stack frame
  447.  
  448.         CLR.W    -(SP)            ; space for result of IsAppWindow
  449.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  450.         BSR    IsAppWindow        ; test if this window was ours
  451.         MOVE.W    (SP)+,D0        
  452.         CMPI.W    #True,D0        ; it must be our window
  453.         BNE.S    Exit            ; it wasn't our window
  454.         
  455.         MOVE.L    WindowPtr(A6),-(SP)    ; update only the visible region
  456.         _BeginUpDate            ; region of the window
  457.         CLR.W    -(SP)            ; space for result
  458.         MOVEA.L    WindowPtr(A6),A0    ; the window pointer
  459.         MOVE.L    visRgn(A0),-(SP)    ; the window's visRgn handle
  460.         _EmptyRgn
  461.         MOVE.W    (SP)+,D0        ; result of EmptyRgn
  462.         CMPI.W    #True,D0        ; was the visRgn empty?
  463.         BEQ.S    @1            ; yes, then no update is needed
  464.         
  465.         MOVE.L    WindowPtr(A6),-(SP)
  466.         BSR    DrawWindow        ; draw the traffic lights
  467.         
  468. @1        MOVE.L    WindowPtr(A6),-(SP)    ; get pointer to window
  469.         _EndUpdate
  470.  
  471. Exit        UNLK    A6            ; destroy the link
  472.         MOVEA.L    (SP)+,A0        ; pull off the return address
  473.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  474.         JMP    (A0)            ; return to the caller
  475.  
  476.         DbgInfo    DoUpdate        ; this name will appear in the debugger
  477.         ENDP
  478.  
  479. * ================================================
  480. * PROCEDURE DoActivate(window: WindowPtr; becomingActive: BOOLEAN);
  481. * ================================================
  482. * In this sample there is no other processing necessary other than what
  483. * the Window Manager has already done for us.  This would be the place to
  484. * perform an activate on TextEdit records, controls, lists, update GrowIcon, etc.
  485.  
  486.         SEG    'Main'            ; case sensitive
  487. DoActivate    PROC
  488.  
  489. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  490. ParamBegin    EQU    *            ; start parameters after this point
  491. WindowPtr    DS.L    1            ; passed parameter of the window pointer
  492. Active        DS.W    1            ; modifiers from the event record
  493. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  494. RetAddr     DS.L    1            ; place holder for return address
  495. A6Link        DS.L    1            ; place holder for A6 link
  496. LocalSize    EQU     *            ; size of all the local variables
  497.         ENDR
  498.         
  499.         IMPORT    IsAppWindow
  500.  
  501.         WITH    StackFrame        ; cover our local stack frame
  502.         LINK    A6,#LocalSize        ; allocate our local stack frame
  503.  
  504.         CLR.W    -(SP)            ; space for result of IsAppWindow
  505.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  506.         BSR    IsAppWindow        ; test if this window was ours
  507.         MOVE.W    (SP)+,D0        ; get the result
  508.         CMPI.W    #True,D0        ; it must be our window
  509.         BNE.S    Exit            ; it wasn't our window
  510.  
  511.         CMPI.W    #True,Active(A6)    ; was it an Activate?
  512.         BNE.S    DeActivate        ; no, perform a Deactivate
  513.         
  514. * do the activate event processing here, then "BRA.S   Exit"
  515.         
  516. DeActivate                    ; do the deactivate event
  517.  
  518. * do the deactivate event processing here, then fall through to Exit
  519.         
  520.  
  521. Exit        UNLK    A6            ; destroy the link
  522.         MOVEA.L    (SP)+,A0        ; pull off the return address
  523.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  524.         JMP    (A0)            ; return to the caller
  525.  
  526.         DbgInfo    Activate        ; this name will appear in the debugger
  527.         ENDP
  528.                     
  529. * ================================================
  530. * PROCEDURE DoMenuCommand(menuResult: LONGINT);
  531. * ================================================
  532. * This is called when an item is chosen from the menu bar (after calling
  533. * MenuSelect or MenuKey). It performs the right operation for each command.
  534. * It is good to have both the result of MenuSelect and MenuKey go to
  535. * one routine like this to keep everything organized.
  536.  
  537.         SEG    'Main'            ; case sensitive
  538. DoMenuCommand    PROC
  539.  
  540. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  541. ParamBegin    EQU    *            ; start parameters after this point
  542. MenuItem    DS.W    1            ; result from _MenuKey or _MenuSelect
  543. MenuID        DS.W    1            ; caller passed a long word, ID + Item
  544. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  545. RetAddr     DS.L    1            ; place holder for return address
  546. A6Link        DS.L    1            ; place holder for A6 link
  547. Deskname    DS.B    256            ; local storage for Desk Accs name
  548. TempPort    DS.L    1            ; local storage for the current port
  549. LocalSize    EQU     *            ; size of all the local variables
  550.         ENDR
  551.         
  552.         IMPORT    SetLight,DoCloseWindow,Terminate
  553.  
  554.         WITH    StackFrame        ; cover our local stack frame
  555.         LINK    A6,#LocalSize        ; allocate our local stack frame
  556.  
  557.         MOVE.W    MenuID(A6),D0        ; a nifty Pascal case-like macro
  558.         CASE#.W    (D0,IF),            \
  559.             (AppleMenu,    DoAppleMenu),    \
  560.             (FileMenu,    DoFileMenu),    \
  561.             (EditMenu,    DoEditMenu),    \
  562.             (LightMenu,    DoLightMenu)
  563.                         ; add additional Menus would go here
  564.         BRA.W    Exit            ; otherwise we will exit this procedure
  565.  
  566. * ------------- THE APPLE MENU ROUTINES -------------
  567. DoAppleMenu
  568.         CMPI.W    #AboutItem,MenuItem(A6)    ; was it the about item?
  569.         BNE.S    @1            ; no, must be a Desk Acc
  570.  
  571.         CLR.W    -(SP)            ; show the About dialog
  572.         MOVE.W    #rAboutAlert,-(SP)    ; resource for alert dialog
  573.         CLR.L    -(SP)            ; no filter procedure used here
  574.         _Alert                ; read the resource and display it
  575.         MOVE.W    (SP)+,D0        ; I don't care which item is was
  576.         BRA.W    Exit            ; all done with with Apple menu
  577.  
  578. @1        PEA    TempPort(A6)        ; open a desk accessory
  579.         _GetPort            ; save the current port
  580.         CLR.L    -(SP)            ; space for result of GetMHandle
  581.         MOVE.W    #AppleMenu,-(SP)
  582.         _GetMHandle            ; put Apple menu on stack
  583.         MOVE.W    MenuItem(A6),-(SP)    ; and here's the MenuItem
  584.         PEA    DeskName(A6)        ; now tell me the DA's name
  585.         _GetItem
  586.         CLR.W    -(SP)            ; space for OpenDeskAcc result
  587.         PEA    DeskName(A6)
  588.         _OpenDeskAcc            ; open that puppy
  589.         MOVE.W    (SP)+,D0        ; result
  590.         MOVE.L    TempPort(A6),-(SP)    ; restore the port
  591.         _SetPort
  592.         BRA.S    Exit
  593.         
  594. * ------------- THE FILE MENU ROUTINES -------------
  595. DoFileMenu    
  596.         MOVE.W    MenuItem(A6),D0     ; test the MenuItem
  597.         Case#.W    (D0,IF),            \
  598.             (CloseItem,    FileClose),    \
  599.             (QuitItem,    FileQuit)
  600.         BRA.S    Exit            ; add additional menus here
  601. FileClose
  602.         CLR.L    -(SP)            ; bug fix, didn't clear space for result -JDR 2/27/89
  603.         _FrontWindow
  604.         BSR    DoCloseWindow        ; close the window 
  605.         BRA.S    Exit
  606.  
  607. FileQuit    BSR    Terminate        ; let's get out of here
  608.         BRA.S    Exit            ; Terminate may return if user cancels
  609.  
  610. * ------------- THE EDIT MENU ROUTINES -------------
  611. DoEditMenu    
  612.         CLR.W    -(SP)            ; system will handle editing of desk accs.
  613.         MOVE.W    MenuItem(A6),-(SP)    ; get the MenuItem
  614.         SUBQ.W    #1,(SP)            ; SystemEdit is off by one
  615.         _SysEdit
  616.         MOVE.B    (SP)+,D0        ; drop result from SystemEdit
  617.         BRA.S    Exit            ; we don't have anything to edit
  618.  
  619. * ------------- THE LIGHT MENU ROUTINES -------------
  620. DoLightMenu    
  621.         MOVE.W    MenuItem(A6),D0     ; test the MenuItem
  622.         Case#.W    (D0,IF),            \
  623.             (StopItem,    StopSelect),    \
  624.             (GoItem,    GoSelect)
  625.         BRA.S    Exit            ; add additional menus here
  626.  
  627. StopSelect    CLR.L    -(SP)            ; bug fix, didn't clear space for result -JDR 2/27/89
  628.         _FrontWindow            ; pass our window, we only have one
  629.         MOVE.W    #TRUE,-(SP)        ; pass true to set stop light on
  630.         BSR    SetLight        ; switch the traffic light
  631.         BRA.S    Exit
  632.  
  633. GoSelect    CLR.L    -(SP)            ; bug fix, didn't clear space for result -JDR 2/27/89
  634.         _FrontWindow            ; pass our window, we only have one
  635.         MOVE.W    #FALSE,-(SP)        ; pass false to set stop light off
  636.         BSR    SetLight        ; switch the traffic light
  637.         
  638. Exit        CLR.W    -(SP)    
  639.         _HiLiteMenu            ; unhilite all Menus
  640.         UNLK    A6            ; destroy the link
  641.         MOVEA.L    (SP)+,A0        ; pull off the return address
  642.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  643.         JMP    (A0)            ; return to the caller
  644.  
  645.         DbgInfo    DoMenuCm        ; this name will appear in the debugger
  646.         ENDP
  647.         
  648. * ================================================
  649. * PROCEDURE DoMouseDown(Event: EventRecord);
  650. * ================================================
  651. * Handle all of the MouseDown events.
  652.  
  653.         SEG    'Main'            ; case sensitive
  654. DoMouseDown    PROC
  655.  
  656. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  657. ParamBegin    EQU    *            ; start parameters after this point
  658. EventPtr     DS.L    1             ; pointer to current event
  659. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  660. RetAddr     DS.L    1            ; place holder for return address
  661. A6Link        DS.L    1            ; place holder for A6 link
  662. WindowPtr    DS.L    1            ; local Window pointer variable
  663. Where        DS.L    1            ; local variable where the click was
  664. NewGrowRect    DS    Rect            ; local rect variable for SizeWindow
  665. LocalSize    EQU     *            ; size of all the local variables
  666.         ENDR
  667.  
  668.         IMPORT    AdjustMenus,DoContentClick
  669.  
  670.         WITH    StackFrame        ; cover our local stack frame
  671.         LINK    A6,#LocalSize        ; allocate our local stack frame
  672.         
  673.         MOVEA.L    EventPtr(A6),A0        ; event record only needed by SystemClick
  674.         MOVE.L    evtMouse(A0),Where(A6)    ; make a local copy of the mouse location
  675.  
  676.         CLR.W    -(SP)            ; space for FindWindow result
  677.         MOVE.L    Where(A6),-(SP)        ; the mouse point
  678.         PEA    WindowPtr(A6)        ; a local variable
  679.         _FindWindow            ; put the result in a register
  680.         MOVE.W    (SP)+,D0        ; a nifty Pascal case-like macro
  681.         Case#.W    (D0,IF),            \
  682.             (InMenuBar,    MenuEvent),    \
  683.             (InSysWindow,    SystemEvent),    \
  684.             (InContent,    Content),    \
  685.             (InDrag,    Drag)
  686.                         ; add additional routines here
  687.         BRA.S    Exit            ; otherwise we will exit this procedure
  688.  
  689. * ------------- THE DESK ACCS EVENT -------------
  690. MenuEvent    
  691.         BSR.W    AdjustMenus
  692.         CLR.L    -(SP)            ; space for MenuSelect
  693.         MOVE.L    Where(A6),-(SP)        ; Mouse coordinates
  694.         _MenuSelect            ; pass MenuSelect's result
  695.         BSR    DoMenuCommand        ; go do the menu and return
  696.         BRA.S    Exit
  697.  
  698. * ------------- THE DESK ACCS EVENT -------------
  699. SystemEvent    
  700.         MOVE.L    EventPtr(A6),-(SP)    ; get EventRecord and WindowPtr
  701.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer and...
  702.         _SystemClick            ; let the system handle it
  703.         BRA.S    Exit
  704.  
  705. * ------------- THE CONTENT EVENT -------------
  706. Content        
  707.         CLR.L    -(SP)            ; was our window in front?
  708.         _FrontWindow            ; get front window's pointer
  709.         MOVE.L    (SP)+,D0
  710.         CMP.L    WindowPtr(A6),D0    ; was it in the front window?
  711.         BNE.S    @1            ; no, then just select window
  712.         
  713.         MOVE.L    WindowPtr(A6),-(SP)    ; pass the window pointer
  714.         MOVE.L    EventPtr(A6),-(SP)    ; pass a pointer to the event
  715.         BSR    DoContentClick        ; do a click in content region
  716.         BRA.S    Exit
  717.         
  718. @1        MOVE.L    WindowPtr(A6),-(SP)    ; only select this window
  719.         _SelectWindow            ; and take no further action
  720.         BRA.S    Exit
  721.  
  722. * ------------- THE DRAG A WINDOW EVENT -------------
  723. Drag        
  724.         MOVE.L    WindowPtr(A6),-(SP)    ; pass Window Pointer
  725.         MOVE.L    Where(A6),-(SP)        ; Mouse coordinates and boundary
  726.         PEA    QD.screenBits + bounds    ; get the bounds of the window
  727.         _DragWindow            ; drag it the screen's boundary
  728.  
  729. Exit        
  730.         UNLK    A6            ; destroy the link
  731.         MOVEA.L    (SP)+,A0        ; pull off the return address
  732.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  733.         JMP    (A0)            ; return to the caller
  734.  
  735.         DbgInfo    MouseDwn        ; this name will appear in the debugger
  736.         ENDP
  737.         
  738.         
  739. * ================================================
  740. * PROCEDURE DoEvent(event: EventRecord);
  741. * ================================================
  742. * Do the right thing for an event. Determine what kind of event it is,
  743. * and call the appropriate routines.
  744.  
  745.         SEG    'Main'            ; case sensitive
  746. DoEvent        PROC
  747.  
  748. ModifyReg    EQU    D4            ; we'll use this register locally
  749.  
  750. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  751. ParamBegin    EQU    *            ; start listing parameters here
  752. EventPtr     DS.L    1             ; pointer to current event
  753. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  754. RetAddr     DS.L    1            ; place holder for return address
  755. A6Link        DS.L    1            ; place holder for A6 link
  756. TheEvent     DS    EventRecord         ; local copy of the event record
  757. LocalSize    EQU     *            ; size of all the local variables
  758.         ENDR
  759.  
  760.         IMPORT    DoMouseDown,DrawWindow,    \
  761.             AdjustMenus,IsAppWindow,\
  762.             DoUpdate,DoActivate
  763.         
  764.         WITH    StackFrame,TheEvent    ; cover our local stack frame
  765.         LINK    A6,#LocalSize        ; allocate our local stack frame
  766.         MOVEM.L    ModifyReg,-(SP)        ; save this register before using it
  767.  
  768.         MOVEA.L    EventPtr(A6),A0        ; pointer of event passed by caller
  769.         LEA    TheEvent(A6),A1        ; pointer to local variable TheEvent
  770.         MOVE.L    #evtBlkSize,D0        ; size of an event record
  771.         _BlockMove            ; we now have a local copy of the event
  772.  
  773.         MOVE.W    Modifiers(A6),ModifyReg    ; a nifty Pascal case-like macro
  774.         MOVE.W    What(A6),D0        ; get the event number
  775.         Case#    (D0,Exit),    \    ; if not an event we support, then exit
  776.             ,        \    ;  0 Null (not used)
  777.             MouseDown,    \    ;  1 Mouse down
  778.             ,        \    ;  2 Mouse up (not used)
  779.             KeyDown,    \    ;  3 Key down
  780.             ,        \    ;  4 Key up (not used)
  781.             KeyDown,    \    ;  5 Auto key
  782.             Update,     \    ;  6 Update
  783.             Disk,        \    ;  7 Disk inserted
  784.             Activate,    \    ;  8 Activate/Deactivate
  785.             ,        \    ;  9 (not used)
  786.             ,        \    ; 10 Network (not used)
  787.             ,        \    ; 11 I/O Driver (not used)
  788.             ,        \    ; 12 App1 (not used)
  789.             ,        \    ; 13 App2 (not used)
  790.             ,        \    ; 14 App3 (not used)
  791.             OSEvent,        ; 15 OS Event or Suspend/Resume
  792.  
  793.  
  794. * ------------- THE MOUSEDOWN EVENT -------------
  795. MouseDown    
  796.         PEA    TheEvent(A6)        ; pass Event pointer in case of SystemClick
  797.         BSR    DoMouseDown
  798.         BRA    Exit
  799.  
  800. * ------------- THE KEYDOWN EVENT -------------
  801. KeyDown        
  802.         BTST    #CmdKey,ModifyReg    ; command key?
  803.         BEQ    Exit            ; no, then we're done
  804.         BSR.W    AdjustMenus        ; first, adjust the menus
  805.         CLR.L    -(SP)            ; space for MenuKey
  806.         MOVE.W    2+Message(A6),-(SP)    ; get the character
  807.         _MenuKey            ; is it a command?
  808.         BSR    DoMenuCommand        ; handle the command and return
  809.         BRA.S    Exit
  810.  
  811. * ------------- THE UPDATE EVENT -------------
  812. Update    
  813.         MOVE.L    Message(A6),-(SP)    ; pass the window pointer
  814.         BSR    DoUpdate        ; do the update
  815.         BRA.S    Exit
  816.  
  817. * ------------- THE DISK EVENT -------------
  818. Disk    
  819.         TST.W    Message(A6)        ; check for error
  820.         BEQ.S    @1            ; if none, skip
  821.         CLR.W    -(SP)
  822.         MOVE.L    #DITopLeft,-(SP)
  823.         MOVE.L    Message(A6),-(SP)
  824.         MOVE.W    #diBadMount,-(SP)
  825.         _Pack2                ; go through disk init package
  826.         ADDQ    #2,SP            ; throw away result
  827. @1        BRA.S    Exit
  828.  
  829. * ------------- THE ACTIVATE/DEACTIVATE EVENT -------------
  830. Activate    
  831.         BTST    #ActiveFlag,ModifyReg    ; was it an Activate?
  832.         BEQ.S    @1            ; no, perform a Deactivate
  833.  
  834.         MOVE.L    Message(A6),-(SP)    ; pass the current window pointer
  835.         MOVE.W    #True,-(SP)        ; set up for an Activate event
  836.         BSR    DoActivate        ; do the activate routine
  837.         BRA.S    Exit            ; we're done
  838.  
  839. @1        MOVE.L    Message(A6),-(SP)    ; pass current window pointer
  840.         MOVE.W    #False,-(SP)        ; set up for an Deactivate event
  841.         BSR    DoActivate        ; go do the activate routine
  842.         BRA.S    Exit            ; we're done
  843.  
  844. * ------------- THE SUSPEND/RESUME EVENT -------------
  845. * OSEvent is the event number of the suspend/resume and mouse-moved events sent
  846. * by MultiFinder. Once we determine that an event is an osEvent, we look at the
  847. * high byte of the message sent to determine which kind it is. To differentiate
  848. * suspend and resume events we check the resumeMask bit.
  849.  
  850. OSEvent        MOVE.B    Message(A6),D1        ; get high byte of Message in reg
  851.         CMPI.B    #SuspendResume,D1    ; test for message event type
  852.         BNE.S    Exit            ; not a suspend/resume event
  853.  
  854.         BTST    #0,3+Message(A6)    ; test bit zero in low byte of Message
  855.         BNE.S    @1            ; this is a resume event
  856.         
  857.         MOVE.W    #True,G.InBackground    ; a suspend event
  858.         CLR.L    -(SP)            ; bug fix, was passing Message to DoActivate -JDR 2/27/89 
  859.         _FrontWindow            ; pass the front window to DoActivate -JDR 2/27/89
  860.         MOVE.W    #False,-(SP)        ; pass false to cause deactivate
  861.         BSR    DoActivate        ; go do the activate routine
  862.         BRA.S    Exit
  863.  
  864. @1        MOVE.W    #False,G.InBackground    ; a resume event
  865.         CLR.L    -(SP)            ; bug fix, was passing Message to DoActivate -JDR 2/27/89 
  866.         _FrontWindow            ; pass the front window to DoActivate -JDR 2/27/89
  867.         MOVE.W    #True,-(SP)        ; pass false to cause activate
  868.         BSR    DoActivate        ; go do the activate routine
  869.         
  870. Exit        
  871.         MOVEM.L    (SP)+,ModifyReg        ; restore this register after use
  872.         UNLK    A6
  873.         MOVEA.L    (SP)+,A0        ; save the caller's address
  874.         ADDA.L    #ParamSize,SP        ; strip the caller's parameters
  875.         JMP    (A0)
  876.  
  877.         DbgInfo    DoEvent            ; this name will appear in the debugger
  878.         ENDP
  879.         
  880. * ================================================
  881. * PROCEDURE EventLoop;
  882. * ================================================
  883. * Get the events by calling WaitNextEvent, if it's available, otherwise
  884. * by calling GetNextEvent. Also call AdjustCursor before doing the event.
  885. * After returning from handling the event, we have to make sure the cursor
  886. * is still adjusted proper ONLY because this application can "sleep" forever.
  887.  
  888. * An event record is allocated on the stack.  A pointer to this event is
  889. * passed to "DoEvent".  We loop until the user has selects "Quit" in the
  890. * file menu.  This program will exit through the DoMenuCommand routine.
  891.  
  892. * 1.02 made adjustments to the event loop logic.  There was a bug in calling
  893. * AdjustCursor at the wrong time. (it crashed under _GetNextEvent too!)
  894.  
  895. * If you are using modeless dialogs that have editText items,
  896. * you will want to call IsDialogEvent to give the caret a chance
  897. * to blink, even if WNE/GNE returned FALSE. However, check FrontWindow
  898. * for a non-NIL value before calling IsDialogEvent.
  899.  
  900.         SEG    'Main'            ; case sensitive
  901. EventLoop    PROC                ; any source file can use this routine
  902.  
  903. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  904. ParamBegin    EQU    *            ; start listing parameters here
  905. ParamSize    EQU    ParamBegin-*        ; size of all the passed parameters
  906. RetAddr     DS.L    1            ; place holder for return address
  907. A6Link        DS.L    1            ; place holder for A6 link
  908. TheEvent     DS    EventRecord         ; local copy of the event record
  909. MouseMvdRgn    DS.L    1            ; local region for MouseMoved events
  910. MousePos    DS.L    1            ; local point for mouse position
  911. LocalSize    EQU     *            ; size of all the local variables
  912.         ENDR
  913.         
  914.         IMPORT    AdjustCursor,GetGlobalMouse
  915.  
  916.         WITH    StackFrame        ; cover our local stack frame
  917.         LINK    A6,#LocalSize        ; allocate our local stack frame
  918.         
  919.         CLR.L    -(SP)
  920.         _NewRgn                ; create region for AdjustCursor
  921.         MOVE.L    (SP)+,MouseMvdRgn(A6)    ; save the handle to this region
  922.  
  923. * ------------- GET NEXT EVENT LOOP -------------
  924. NextEvent    
  925.         CMPI.W    #True,G.HasWNEvent     ; see if we can call WaitNextEvent
  926.         BNE.S    @1            ; nope, old time events
  927.         
  928.         PEA    MousePos(A6)        ; here's the mouse
  929.         BSR    GetGlobalMouse        ; get global coordinate
  930.         MOVE.L    MousePos(A6),-(SP)    ; here's the mouse
  931.         MOVE.L    MouseMvdRgn(A6),-(SP)    ; the region to change
  932.         BSR    AdjustCursor        ; adjust the cursor and region
  933.         CLR.W    -(SP)            ; space for result
  934.         MOVE.W    #EveryEvent,-(SP)    ; the events we want
  935.         PEA    TheEvent(A6)        ; pointer to the event record
  936.         MOVE.L    #SleepValue,-(SP)    ; the sleeping time value
  937.         MOVE.L    MouseMvdRgn(A6),-(SP)    ; the current MouseRgn
  938.         _WaitNextEvent
  939.         BRA.S    @2            ; got an event to handle?
  940.     
  941.                         ; no WaitNextEvent trap available
  942. @1        _SystemTask            ; call SystemTask for drivers and DAs
  943.         CLR.W    -(SP)            ; space for result
  944.         MOVE.W    #EveryEvent,-(SP)    ; the events we want
  945.         PEA    TheEvent(A6)        ; pass a pointer to our event
  946.         _GetNextEvent
  947. @2        MOVE.W    (SP)+,D0        ; result code
  948.         BEQ.S    NextEvent        ; no event, get another one
  949.         
  950. GotEvent    MOVE.L    TheEvent.where(A6),-(SP); the mouse location
  951.         MOVE.L    MouseMvdRgn(A6),-(SP)    ; the region to change
  952.         BSR    AdjustCursor        ; adjust cursor BEFORE doing event
  953.         PEA    TheEvent(A6)        ; pass the pointer to our event
  954.         BSR    DoEvent            ; do the event and return
  955.  
  956.         BRA.S    NextEvent        ; done with that event, get the next
  957.  
  958. Exit        UNLK    A6            ; destroy the link
  959.         MOVEA.L    (SP)+,A0        ; pull off the return address
  960.         ADDA.L    #ParamSize,SP        ; strip all of the caller's parameters
  961.         JMP    (A0)            ; return to the caller
  962.  
  963.         DbgInfo    EvntLoop        ; this name will appear in the debugger
  964.         ENDP
  965.  
  966. * ================================================
  967. * --------------- MAIN ENTRY POINT ---------------
  968. * ================================================
  969. * This is the entry point of the program.  We start with data initializing
  970. * and then to get the System environment (SysEnvirons).  We unload the
  971. * initialization code segment and finally get started with the EventLoop.
  972.  
  973.         SEG    'Main'            ; case sensitive
  974. StartUp            MAIN                ; entry point of the program
  975.         
  976.         IMPORT    _DataInit,Initialize,    \
  977.             ForceEnvirons,EventLoop
  978.  
  979.         JSR    _DataInit        ; initialize those constants    
  980.         PEA    _DataInit        ; get rid of that segment
  981.         _UnloadSeg
  982.  
  983. * If you have stack requirements that differ from the default, then you could
  984. * use SetApplLimit to increase StackSpace at this point, before calling MaxApplZone.
  985.  
  986.         _MaxApplZone            ; result in D0
  987.         JSR    Initialize        ; get things the program set up
  988.         PEA    Initialize
  989.         _UnloadSeg            ; we're done this that segment too
  990.         LEA    EventLoop,A0        ; on your mark, get set,...
  991.         JMP    (A0)            ; go into the event loop
  992.         ENDP
  993.  
  994.         END                ; end of this source file
  995.  
  996.